package com.sqlcheck.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sqlcheck.dto.request.CreateScanTaskRequest;
import com.sqlcheck.dto.response.ScanTaskResponse;
import com.sqlcheck.entity.Project;
import com.sqlcheck.entity.ScanTask;
import com.sqlcheck.entity.User;
import com.sqlcheck.common.exception.BusinessException;
import com.sqlcheck.enums.GitPlatform;
import com.sqlcheck.repository.ProjectRepository;
import com.sqlcheck.repository.ScanResultRepository;
import com.sqlcheck.repository.ScanTaskRepository;
import com.sqlcheck.repository.SqlStatementRepository;
import com.sqlcheck.repository.UserRepository;
import com.sqlcheck.service.ScanTaskService;
import com.sqlcheck.service.TemporaryCredentialService;
import com.sqlcheck.service.UserContextService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import com.sqlcheck.enums.TaskStatus;
import com.sqlcheck.enums.TaskType;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class ScanTaskServiceImpl implements ScanTaskService {

    private final ScanTaskRepository scanTaskRepository;
    private final UserRepository userRepository;
    private final ProjectRepository projectRepository;
    private final ScanResultRepository scanResultRepository;
    private final SqlStatementRepository sqlStatementRepository;
    private final UserContextService userContextService;
    private final TemporaryCredentialService temporaryCredentialService;

    @Override
    @Transactional
    public ScanTaskResponse createTask(CreateScanTaskRequest request, Long userId) {
        log.info("创建扫描任务: {}, 用户ID: {}, 请求: {}", request.getTaskName(), userId, request);

        // 验证用户存在
        User user = userRepository.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        // 如果指定了项目，验证项目存在且用户有权限
        if (request.getProjectId() != null) {
            Project project = projectRepository.selectById(request.getProjectId());
            if (project == null) {
                throw new BusinessException("项目不存在");
            }
            if (!project.getOwnerId().equals(userId)) {
                throw new BusinessException("无权限访问该项目");
            }
        }

        // 创建任务
        ScanTask task = new ScanTask()
                .setTaskName(request.getTaskName())
                .setTaskType(TaskType.valueOf(request.getTaskType()))
                .setStatus(TaskStatus.PENDING)
                .setProgress(TaskStatus.PENDING.getDefaultProgress())
                .setProjectId(request.getProjectId())
                .setBranchName(request.getBranchName())
                .setUserId(userId)
                .setDescription(request.getDescription())
                .setConfig(request.getConfig())
                .setSourceDbType(request.getSourceDbType())
                .setTargetDbType(request.getTargetDbType())
                .setAiEnhancementEnabled(request.getAiEnhancementEnabled())
                .setRetryCount(0)
                .setMaxRetryCount(3); // 默认最大重试3次

        scanTaskRepository.insert(task);

        return convertToResponse(task);
    }

    @Override
    public ScanTaskResponse getTaskById(Long taskId, Long currentUserId) {
        ScanTask task = scanTaskRepository.selectById(taskId);
        if (task == null) {
            throw new BusinessException("任务不存在");
        }

        // 权限检查
        if (currentUserId != null && !userContextService.canAccessTask(currentUserId, task.getUserId())) {
            throw new BusinessException("无权限访问此任务");
        }

        return convertToResponse(task);
    }

    @Override
    public ScanTask getTaskByIdInternal(Long taskId) {
        ScanTask task = scanTaskRepository.selectById(taskId);
        if (task == null) {
            throw new BusinessException("任务不存在");
        }

        return task;
    }

    @Override
    public IPage<ScanTaskResponse> getTasksByUserId(Long userId, Page<ScanTask> page, Long currentUserId) {
        log.debug("获取用户任务列表: userId={}, currentUserId={}", userId, currentUserId);

        // 权限检查：只有管理员或查询自己的任务
        if (currentUserId != null && !userContextService.canAccessTask(currentUserId, userId)) {
            log.warn("权限不足: currentUserId={}, targetUserId={}", currentUserId, userId);
            throw new BusinessException("无权限查看此用户的任务");
        }

        // 根据用户权限获取数据过滤条件
        Long filterUserId = userContextService.getDataFilterUserId(currentUserId);
        log.debug("数据过滤条件: filterUserId={}", filterUserId);

        IPage<ScanTask> taskPage;
        if (filterUserId == null) {
            // 管理员查看所有任务
            taskPage = scanTaskRepository.findAllTasksWithPage(page);
        } else {
            // 普通用户只能查看自己的任务
            taskPage = scanTaskRepository.findByUserIdWithPage(page, filterUserId);
        }

        log.debug("查询结果: 总数={}, 当前页记录数={}", taskPage.getTotal(), taskPage.getRecords().size());
        return taskPage.convert(this::convertToResponse);
    }

    @Override
    public List<ScanTaskResponse> getTasksByProjectId(Long projectId, Long currentUserId) {
        // 根据用户权限获取数据过滤条件
        Long filterUserId = currentUserId != null ? userContextService.getDataFilterUserId(currentUserId) : null;

        List<ScanTask> tasks = scanTaskRepository.findByProjectIdWithPermission(projectId, filterUserId);
        return tasks.stream()
                .map(this::convertToResponse)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public ScanTaskResponse updateTaskStatus(Long taskId, TaskStatus status, Integer progress) {
        log.info("更新任务状态: taskId={}, status={}, progress={}", taskId, status, progress);

        ScanTask task = scanTaskRepository.selectById(taskId);
        if (task == null) {
            throw new BusinessException("任务不存在");
        }

        // 更新状态和进度
        task.setStatus(status);

        // 如果进度为null，使用枚举的默认进度值
        if (progress != null) {
            task.setProgress(progress);
        } else {
            task.setProgress(status.getDefaultProgress());
        }

        // 根据状态设置时间
        if (status == TaskStatus.RUNNING && task.getStartTime() == null) {
            task.setStartTime(LocalDateTime.now());
        } else if (status.isFinalState()) {
            task.setEndTime(LocalDateTime.now());
        }

        scanTaskRepository.updateById(task);
        return convertToResponse(task);
    }

    @Override
    @Transactional
    public ScanTaskResponse updateTaskError(Long taskId, String errorMessage) {
        log.error("任务执行失败: taskId={}, error={}", taskId, errorMessage);

        ScanTask task = scanTaskRepository.selectById(taskId);
        if (task == null) {
            throw new BusinessException("任务不存在");
        }

        task.setStatus(TaskStatus.FAILED)
                .setErrorMessage(errorMessage)
                .setEndTime(LocalDateTime.now())
                .setProgress(TaskStatus.FAILED.getDefaultProgress());

        scanTaskRepository.updateById(task);
        return convertToResponse(task);
    }

    @Override
    @Transactional
    public void deleteTask(Long taskId, Long userId) {
        log.info("删除任务: taskId={}, 操作用户: {}", taskId, userId);

        ScanTask task = scanTaskRepository.selectById(taskId);
        if (task == null) {
            throw new BusinessException("任务不存在");
        }

        // 验证权限：只有任务创建者可以删除
        if (!task.getUserId().equals(userId)) {
            throw new BusinessException("无权限删除此任务");
        }

        // 只能删除已完成或失败的任务
        if (task.getStatus() == TaskStatus.RUNNING ||
                task.getStatus() == TaskStatus.PENDING) {
            throw new BusinessException("正在执行的任务不能删除");
        }

        scanTaskRepository.deleteById(taskId);
        log.info("任务删除成功: taskId={}", taskId);
    }

    @Override
    @Transactional
    public void startTask(Long taskId) {
        log.info("启动任务: taskId={}", taskId);

        ScanTask task = scanTaskRepository.selectById(taskId);
        if (task == null) {
            throw new BusinessException("任务不存在");
        }

        TaskStatus currentStatus = task.getStatus();

        // 使用枚举方法进行状态判断
        if (currentStatus == TaskStatus.RUNNING) {
            throw new BusinessException("正在执行的任务不能重复启动");
        }

        // 清理历史结果（软删除）
        scanResultRepository.softDeleteByTaskId(taskId);

        // 清理历史SQL语句（软删除），避免重试时唯一约束冲突
        int deletedSqlStatements = sqlStatementRepository.softDeleteByTaskId(taskId);
        log.info("清理历史SQL语句: taskId={}, 删除数量={}", taskId, deletedSqlStatements);

        // 重置并启动 - 使用枚举方法设置状态
        task.setStatus(TaskStatus.RUNNING)
                .setStartTime(LocalDateTime.now())
                .setEndTime(null)
                .setErrorMessage(null)
                .setProgress(TaskStatus.RUNNING.getDefaultProgress());

        scanTaskRepository.updateById(task);
    }

    @Override
    @Transactional
    public void cancelTask(Long taskId) {
        log.info("取消任务: taskId={}", taskId);

        ScanTask task = scanTaskRepository.selectById(taskId);
        if (task == null) {
            throw new BusinessException("任务不存在");
        }

        TaskStatus currentStatus = task.getStatus();

        // 使用枚举方法进行状态判断
        if (!currentStatus.canCancel()) {
            throw new BusinessException("当前状态的任务不能取消");
        }

        task.setStatus(TaskStatus.CANCELLED)
                .setEndTime(LocalDateTime.now())
                .setProgress(TaskStatus.CANCELLED.getDefaultProgress());

        scanTaskRepository.updateById(task);
    }

    @Override
    public List<ScanTaskResponse> getRunningTasks() {
        List<ScanTask> tasks = scanTaskRepository.findByStatus(TaskStatus.RUNNING);
        return tasks.stream()
                .map(this::convertToResponse)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public ScanTaskResponse retryTask(Long taskId, Long userId) {
        log.info("重试任务: taskId={}, userId={}", taskId, userId);

        ScanTask task = scanTaskRepository.selectById(taskId);
        if (task == null) {
            throw new BusinessException("任务不存在");
        }

        // 验证任务所有者权限
        if (!task.getUserId().equals(userId)) {
            throw new BusinessException("无权限操作此任务");
        }

        // 验证任务状态是否可以重试
        if (!canRetryInternal(task)) {
            throw new BusinessException("任务当前状态不支持重试");
        }

        // 增加重试次数
        int currentRetryCount = task.getRetryCount() != null ? task.getRetryCount() : 0;
        int maxRetryCount = task.getMaxRetryCount() != null ? task.getMaxRetryCount() : 3; // 默认最大重试3次

        if (currentRetryCount >= maxRetryCount) {
            throw new BusinessException("任务已达到最大重试次数");
        }

        // 重置任务状态 - 使用枚举方法设置状态和进度
        task.setStatus(TaskStatus.PENDING)
                .setProgress(TaskStatus.PENDING.getDefaultProgress())
                .setErrorMessage(null)
                .setEndTime(null)
                .setRetryCount(currentRetryCount + 1)
                .setLastRetryTime(LocalDateTime.now());

        scanTaskRepository.updateById(task);

        log.info("任务重试成功: taskId={}, 重试次数: {}/{}", taskId, currentRetryCount + 1, maxRetryCount);
        return convertToResponse(task);
    }

    @Override
    public boolean canRetry(Long taskId) {
        ScanTask task = scanTaskRepository.selectById(taskId);
        if (task == null) {
            return false;
        }
        return canRetryInternal(task);
    }

    @Override
    public Map<String, Object> checkTaskCredentials(Long taskId) {
        Map<String, Object> result = new HashMap<>();

        ScanTask task = scanTaskRepository.selectById(taskId);
        if (task == null) {
            result.put("hasValidCredentials", false);
            result.put("gitCredentialValid", false);
            result.put("databaseCredentialValid", false);
            return result;
        }

        boolean gitCredentialValid = true;
        boolean databaseCredentialValid = true;
        String gitTokenExpiredAt = null;

        // 检查任务类型，判断需要哪些凭证
        TaskType taskType = task.getTaskType();

        // 手动SQL类型不需要凭证检查
        if (taskType == TaskType.MANUAL_SQL) {
            result.put("hasValidCredentials", true);
            result.put("gitCredentialValid", true);
            result.put("databaseCredentialValid", true);
            return result;
        }

        // 检查Git凭证（适用于GIT_SCAN
        if (taskType == TaskType.GIT_SOURCE_SCAN) {

            // 从任务配置中获取Git平台信息
            Map<String, Object> config = task.getConfig();
            if (config != null) {
                String gitUrl = (String) config.get("gitRepositoryUrl");
                if (gitUrl != null) {
                    // 判断Git平台
                    GitPlatform platform = determineGitPlatform(gitUrl);

                    // 检查临时凭证是否有效
                    String gitToken = temporaryCredentialService.getGitToken(taskId, platform);
                    gitCredentialValid = gitToken != null;

                    // 如果凭证无效，尝试获取用户的长期凭证
                    if (!gitCredentialValid) {
                        User user = userRepository.selectById(task.getUserId());
                        if (user != null && user.getTokenExpiresAt() != null) {
                            gitCredentialValid = user.getTokenExpiresAt().isAfter(LocalDateTime.now());
                            if (user.getTokenExpiresAt() != null) {
                                gitTokenExpiredAt = user.getTokenExpiresAt().toString();
                            }
                        }
                    }
                }
            }
        }

        // 检查数据库凭证（适用于DATABASE_SCAN）
        if (taskType == TaskType.DATABASE_DDL_SCAN) {

            // 检查临时数据库密码是否有效
            String dbPassword = temporaryCredentialService.getDatabasePassword(taskId);
            databaseCredentialValid = dbPassword != null;

            // 如果没有临时凭证，检查任务配置中的数据库连接是否仍然有效
            if (!databaseCredentialValid) {
                Map<String, Object> config = task.getConfig();
                if (config != null) {
                    // 这里可以添加数据库连接有效性测试
                    // 为简化实现，暂时认为配置存在即有效
                    databaseCredentialValid = config.get("databaseHost") != null;
                }
            }
        }

        boolean hasValidCredentials = gitCredentialValid && databaseCredentialValid;

        result.put("hasValidCredentials", hasValidCredentials);
        result.put("gitCredentialValid", gitCredentialValid);
        result.put("databaseCredentialValid", databaseCredentialValid);
        if (gitTokenExpiredAt != null) {
            result.put("gitTokenExpiredAt", gitTokenExpiredAt);
        }

        log.info("检查任务凭证: taskId={}, hasValidCredentials={}, git={}, db={}",
                taskId, hasValidCredentials, gitCredentialValid, databaseCredentialValid);

        return result;
    }

    /**
     * 根据Git URL判断平台类型
     */
    private GitPlatform determineGitPlatform(String gitUrl) {
        if (gitUrl.contains("gitlab")) {
            return GitPlatform.GITLAB;
        } else if (gitUrl.contains("github")) {
            return GitPlatform.GITHUB;
        } else if (gitUrl.contains("gitee")) {
            return GitPlatform.GITEE;
        }
        return GitPlatform.GITLAB; // 默认
    }

    private boolean canRetryInternal(ScanTask task) {
        TaskStatus status = task.getStatus();

        // 使用枚举方法判断是否可以重试
        if (!status.canRetry() && !status.isFinalState()) {
            return false;
        }

        // 检查重试次数限制
        int currentRetryCount = task.getRetryCount() != null ? task.getRetryCount() : 0;
        int maxRetryCount = task.getMaxRetryCount() != null ? task.getMaxRetryCount() : 3;

        return currentRetryCount < maxRetryCount;
    }

    private ScanTaskResponse convertToResponse(ScanTask task) {
        ScanTaskResponse response = new ScanTaskResponse();
        BeanUtils.copyProperties(task, response);

        // 转换枚举为字符串
        response.setTaskType(task.getTaskType().name());
        response.setStatus(task.getStatus().name());

        // 设置配置和统计信息
        response.setConfig(task.getConfig());
        response.setExtractionStats(task.getExtractionStats());

        // 设置AI增强分析相关字段
        response.setSourceDbType(task.getSourceDbType());
        response.setTargetDbType(task.getTargetDbType());
        response.setAiEnhancementEnabled(task.getAiEnhancementEnabled());
        response.setAiAnalysisStatus(task.getAiAnalysisStatus());
        response.setAiAnalysisStartTime(task.getAiAnalysisStartTime());
        response.setAiAnalysisEndTime(task.getAiAnalysisEndTime());
        response.setAiAnalysisDuration(task.getAiAnalysisDuration());
        response.setAiProcessedSqlCount(task.getAiProcessedSqlCount());
        response.setAiSkipReason(task.getAiSkipReason());
        response.setAiFilterConfig(task.getAiFilterConfig());

        // 添加重试相关信息
        response.setRetryCount(task.getRetryCount() != null ? task.getRetryCount() : 0);
        response.setMaxRetryCount(task.getMaxRetryCount() != null ? task.getMaxRetryCount() : 3);
        response.setCanRetry(canRetryInternal(task));

        // 填充用户名信息
        if (task.getUserId() != null) {
            User user = userRepository.selectById(task.getUserId());
            if (user != null) {
                response.setUsername(user.getUsername());
            }
        }

        // 填充增强显示字段
        populateEnhancedDisplayFields(response, task);
        log.debug("转换任务响应: response={}", response);
        return response;
    }

    /**
     * 填充增强显示字段，用于前端统一显示
     */
    private void populateEnhancedDisplayFields(ScanTaskResponse response, ScanTask task) {
        Map<String, Object> config = task.getConfig();
        // 修复：检查config为null或空Map的情况
        if (config == null || config.isEmpty()) {
            // 即使config为空，也要设置默认的增强显示字段
            response.setAnalysisEngineDisplay("规则引擎");
            response.setDataSourceDisplay("");
            response.setSourceDbType(null);
            response.setTargetDbType(null);
            return;
        }

        try {
            // 1. 分析引擎显示
            String analysisEngine = (String) config.get("analysisEngine");
            if (analysisEngine != null) {
                switch (analysisEngine.toUpperCase()) {
                    case "AI_ANALYSIS":
                        response.setAnalysisEngineDisplay("AI引擎");
                        break;
                    case "RULE_BASED":
                        response.setAnalysisEngineDisplay("规则引擎");
                        break;
                    case "HYBRID":
                        response.setAnalysisEngineDisplay("混合模式");
                        break;
                    default:
                        response.setAnalysisEngineDisplay("规则引擎"); // 默认值
                }
            } else {
                response.setAnalysisEngineDisplay("规则引擎"); // 默认值
            }

            // 2. 数据库类型
            String sourceDbType = (String) config.get("sourceDbType");
            String targetDbType = (String) config.get("targetDbType");
            response.setSourceDbType(sourceDbType);
            response.setTargetDbType(targetDbType);

            // 3. 数据源信息显示
            String dataSourceDisplay = buildDataSourceDisplay(config, sourceDbType);
            response.setDataSourceDisplay(dataSourceDisplay);

        } catch (Exception e) {
            log.warn("填充增强显示字段失败: taskId={}", task.getId(), e);
            // 设置默认值
            response.setAnalysisEngineDisplay("规则引擎");
            response.setDataSourceDisplay("");
        }
    }

    /**
     * 构建数据源显示信息
     */
    private String buildDataSourceDisplay(Map<String, Object> config, String sourceDbType) {
        try {
            // 数据库扫描类型：显示数据库连接信息
            if (config.containsKey("databaseHost")) {
                String host = (String) config.get("databaseHost");
                Object portObj = config.get("databasePort");
                String database = (String) config.get("databaseName");

                if (host != null && !host.trim().isEmpty()) {
                    StringBuilder display = new StringBuilder();

                    // 添加数据库类型标识
                    if (sourceDbType != null) {
                        display.append(sourceDbType.toUpperCase()).append(": ");
                    }

                    display.append(host);

                    // 添加端口（如果有）
                    if (portObj != null) {
                        String port = portObj.toString();
                        if (!port.trim().isEmpty()) {
                            display.append(":").append(port);
                        }
                    }

                    // 添加数据库名（如果有）
                    if (database != null && !database.trim().isEmpty()) {
                        display.append("/").append(database);
                    }

                    return display.toString();
                }
            }

            // Git扫描类型：显示Git仓库信息
            if (config.containsKey("repositoryUrl")) {
                String repoUrl = (String) config.get("repositoryUrl");
                String gitPlatform = (String) config.get("gitPlatform");

                if (repoUrl != null && !repoUrl.trim().isEmpty()) {
                    // 提取仓库名
                    String repoName = extractRepositoryName(repoUrl);
                    if (gitPlatform != null) {
                        return gitPlatform.toUpperCase() + ": " + repoName;
                    } else {
                        return "Git: " + repoName;
                    }
                }
            }

            // 手动SQL：显示SQL片段
            if (config.containsKey("sqlContent")) {
                return "手动SQL输入";
            }

            return ""; // 没有识别到数据源信息

        } catch (Exception e) {
            log.debug("构建数据源显示信息失败", e);
            return "";
        }
    }

    /**
     * 从Git URL中提取仓库名
     */
    private String extractRepositoryName(String repoUrl) {
        try {
            if (repoUrl == null || repoUrl.trim().isEmpty()) {
                return "";
            }

            // 处理各种Git URL格式
            String url = repoUrl.trim();

            // 移除.git后缀
            if (url.endsWith(".git")) {
                url = url.substring(0, url.length() - 4);
            }

            // 提取最后一个路径段作为仓库名
            String[] parts = url.split("/");
            if (parts.length > 0) {
                return parts[parts.length - 1];
            }

            return url;
        } catch (Exception e) {
            log.debug("提取仓库名失败: {}", repoUrl, e);
            return repoUrl;
        }
    }

    @Override
    public ScanTask findById(Long taskId) {
        return scanTaskRepository.selectById(taskId);
    }

    @Override
    public void updateTaskExtractionStats(Long taskId, Map<String, Object> extractionStats) {
        try {
            ScanTask task = scanTaskRepository.selectById(taskId);
            if (task == null) {
                throw new RuntimeException("任务不存在: taskId=" + taskId);
            }

            // 更新提取统计信息
            task.setExtractionStats(extractionStats);

            // 更新到数据库
            int updated = scanTaskRepository.updateById(task);
            if (updated <= 0) {
                throw new RuntimeException("更新任务统计信息失败: taskId=" + taskId);
            }

            log.info("任务统计信息更新成功: taskId={}, stats={}", taskId, extractionStats);

        } catch (Exception e) {
            log.error("更新任务统计信息失败: taskId={}", taskId, e);
            throw new RuntimeException("更新任务统计信息失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional
    public void updateTaskAIAnalysisStatus(Long taskId, String status) {
        ScanTask task = scanTaskRepository.selectById(taskId);
        if (task == null) {
            throw new BusinessException("任务不存在: taskId=" + taskId);
        }

        task.setAiAnalysisStatus(status);
        scanTaskRepository.updateById(task);
        log.debug("更新任务AI分析状态: taskId={}, status={}", taskId, status);
    }

    @Override
    @Transactional
    public void updateTaskAIAnalysisStartTime(Long taskId) {
        ScanTask task = scanTaskRepository.selectById(taskId);
        if (task == null) {
            throw new BusinessException("任务不存在: taskId=" + taskId);
        }

        LocalDateTime now = LocalDateTime.now();
        task.setAiAnalysisStatus("RUNNING");
        task.setAiAnalysisStartTime(now);
        scanTaskRepository.updateById(task);
        log.info("AI分析阶段开始: taskId={}, startTime={}", taskId, now);
    }

    @Override
    @Transactional
    public void updateTaskAIAnalysisCompleted(Long taskId, Integer processedSqlCount, Long duration) {
        ScanTask task = scanTaskRepository.selectById(taskId);
        if (task == null) {
            throw new BusinessException("任务不存在: taskId=" + taskId);
        }

        LocalDateTime now = LocalDateTime.now();
        task.setAiAnalysisStatus("COMPLETED");
        task.setAiAnalysisEndTime(now);
        task.setAiAnalysisDuration(duration);
        task.setAiProcessedSqlCount(processedSqlCount);
        scanTaskRepository.updateById(task);
        log.info("AI分析阶段完成: taskId={}, processedCount={}, duration={}ms", taskId, processedSqlCount, duration);
    }

    @Override
    @Transactional
    public void updateTaskAIAnalysisSkipped(Long taskId, String reason) {
        ScanTask task = scanTaskRepository.selectById(taskId);
        if (task == null) {
            throw new BusinessException("任务不存在: taskId=" + taskId);
        }

        task.setAiAnalysisStatus("SKIPPED");
        task.setAiSkipReason(reason);
        task.setAiAnalysisEndTime(LocalDateTime.now());
        scanTaskRepository.updateById(task);
        log.info("AI分析阶段跳过: taskId={}, reason={}", taskId, reason);
    }
}